#include "FGSFile.h"
#include <stdio.h>
#include <memory>
#include "Utility/Utility.h"
#include "assert.h"
#include<format>
#ifdef _DEBUG
#pragma comment(lib, "opencv_core2413d.lib")
#pragma comment(lib, "opencv_highgui2413d.lib")
#else
#pragma comment(lib, "opencv_core2413.lib")
#pragma comment(lib, "opencv_highgui2413.lib")
#endif

FGSFile::FGSFile(void)
{
	//palette.resize(256);    
	//for (int i = 0; i < 256; ++i) {
	//	palette[i] = cv::Vec3b(i, 255 - i, (i + 128) % 256);
	//}

	//palette = {
	//{0, 0, 0}, {128, 0, 0}, {0, 128, 0}, {128, 128, 0}, {0, 0, 128}, {128, 0, 128}, {0, 128, 128}, {192, 192, 192},
	//{128, 128, 128}, {255, 0, 0}, {0, 255, 0}, {255, 255, 0}, {0, 0, 255}, {255, 0, 255}, {0, 255, 255}, {255, 255, 255},
	//{0, 0, 0}, {0, 0, 95}, {0, 0, 135}, {0, 0, 175}, {0, 0, 215}, {0, 0, 255}, {0, 95, 0}, {0, 95, 95},
	//{0, 95, 135}, {0, 95, 175}, {0, 95, 215}, {0, 95, 255}, {0, 135, 0}, {0, 135, 95}, {0, 135, 135}, {0, 135, 175},
	//{0, 135, 215}, {0, 135, 255}, {0, 175, 0}, {0, 175, 95}, {0, 175, 135}, {0, 175, 175}, {0, 175, 215}, {0, 175, 255},
	//{0, 215, 0}, {0, 215, 95}, {0, 215, 135}, {0, 215, 175}, {0, 215, 215}, {0, 215, 255}, {0, 255, 0}, {0, 255, 95},
	//{0, 255, 135}, {0, 255, 175}, {0, 255, 215}, {0, 255, 255}, {95, 0, 0}, {95, 0, 95}, {95, 0, 135}, {95, 0, 175},
	//{95, 0, 215}, {95, 0, 255}, {95, 95, 0}, {95, 95, 95}, {95, 95, 135}, {95, 95, 175}, {95, 95, 215}, {95, 95, 255},
	//{95, 135, 0}, {95, 135, 95}, {95, 135, 135}, {95, 135, 175}, {95, 135, 215}, {95, 135, 255}, {95, 175, 0}, {95, 175, 95},
	//{95, 175, 135}, {95, 175, 175}, {95, 175, 215}, {95, 175, 255}, {95, 215, 0}, {95, 215, 95}, {95, 215, 135}, {95, 215, 175},
	//{95, 215, 215}, {95, 215, 255}, {95, 255, 0}, {95, 255, 95}, {95, 255, 135}, {95, 255, 175}, {95, 255, 215}, {95, 255, 255},
	//{135, 0, 0}, {135, 0, 95}, {135, 0, 135}, {135, 0, 175}, {135, 0, 215}, {135, 0, 255}, {135, 95, 0}, {135, 95, 95},
	//{135, 95, 135}, {135, 95, 175}, {135, 95, 215}, {135, 95, 255}, {135, 135, 0}, {135, 135, 95}, {135, 135, 135}, {135, 135, 175},
	//{135, 135, 215}, {135, 135, 255}, {135, 175, 0}, {135, 175, 95}, {135, 175, 135}, {135, 175, 175}, {135, 175, 215}, {135, 175, 255},
	//{135, 215, 0}, {135, 215, 95}, {135, 215, 135}, {135, 215, 175}, {135, 215, 215}, {135, 215, 255}, {135, 255, 0}, {135, 255, 95},
	//{135, 255, 135}, {135, 255, 175}, {135, 255, 215}, {135, 255, 255}, {175, 0, 0}, {175, 0, 95}, {175, 0, 135}, {175, 0, 175},
	//{175, 0, 215}, {175, 0, 255}, {175, 95, 0}, {175, 95, 95}, {175, 95, 135}, {175, 95, 175}, {175, 95, 215}, {175, 95, 255},
	//{175, 135, 0}, {175, 135, 95}, {175, 135, 135}, {175, 135, 175}, {175, 135, 215}, {175, 135, 255}, {175, 175, 0}, {175, 175, 95},
	//{175, 175, 135}, {175, 175, 175}, {175, 175, 215}, {175, 175, 255}, {175, 215, 0}, {175, 215, 95}, {175, 215, 135}, {175, 215, 175},
	//{175, 215, 215}, {175, 215, 255}, {175, 255, 0}, {175, 255, 95}, {175, 255, 135}, {175, 255, 175}, {175, 255, 215}, {175, 255, 255},
	//{215, 0, 0}, {215, 0, 95}, {215, 0, 135}, {215, 0, 175}, {215, 0, 215}, {215, 0, 255}, {215, 95, 0}, {215, 95, 95},
	//{215, 95, 135}, {215, 95, 175}, {215, 95, 215}, {215, 95, 255}, {215, 135, 0}, {215, 135, 95}, {215, 135, 135}, {215, 135, 175},
	//{215, 135, 215}, {215, 135, 255}, {215, 175, 0}, {215, 175, 95}, {215, 175, 135}, {215, 175, 175}, {215, 175, 215}, {215, 175, 255},
	//{215, 215, 0}, {215, 215, 95}, {215, 215, 135}, {215, 215, 175}, {215, 215, 215}, {215, 215, 255}, {215, 255, 0}, {215, 255, 95},
	//{215, 255, 135}, {215, 255, 175}, {215, 255, 215}, {215, 255, 255}, {255, 0, 0}, {255, 0, 95}, {255, 0, 135}, {255, 0, 175},
	//{255, 0, 215}, {255, 0, 255}, {255, 95, 0}, {255, 95, 95}, {255, 95, 135}, {255, 95, 175}, {255, 95, 215}, {255, 95, 255},
	//{255, 135, 0}, {255, 135, 95}, {255, 135, 135}, {255, 135, 175}, {255, 135, 215}, {255, 135, 255}, {255, 175, 0}, {255, 175, 95},
	//{255, 175, 135}, {255, 175, 175}, {255, 175, 215}, {255, 175, 255}, {255, 215, 0}, {255, 215, 95}, {255, 215, 135}, {255, 215, 175},
	//{255, 215, 215}, {255, 215, 255}, {255, 255, 0}, {255, 255, 95}, {255, 255, 135}, {255, 255, 175}, {255, 255, 215}, {255, 255, 255}
	//};
}

bool FGSFile::Load(const char* pcFileName)
{
	std::string palName = pcFileName;
	Utility_ReplaceString(palName, ".fgs", ".pal");

	long size1;
	auto data = Utility_GetDataFromFile(palName, size1);
	if (data == 0)
		return false;
	palette.resize(256);
	memcpy(&palette[0], data, size1);
	free(data);
	m_name = GetFileName(pcFileName);
	Utility_ReplaceString(m_name, ".fgs", "");
	if (m_unKnow1 != 0)
	{
		free(m_unKnow1);
		m_unKnow1 = 0;
	}
	if (m_pInfo != 0)
	{
		free(m_pInfo);
	}
	long size;
	m_pInfo = (Info*)Utility_GetDataFromFile(pcFileName, size);

	m_unKnow1 = (Info2**)calloc(1, 4* m_pInfo->count);

	char* pData = (char*)m_pInfo;
	m_unKnow2 = pData + sizeof(Info);

	pData = (char*)m_unKnow2;
	int total_size = 0;
	for (int i = 0; i < m_pInfo->count; i++)
	{			
		Info2* pInfo = (Info2*)pData;
		int size = 36;
		if (pInfo->m_unKnow1.value)
		{
			size = pInfo->size + 48;
			total_size += pInfo->size;
		}
		else
		{
		}
		m_unKnow1[i] = (Info2*)pData;
		pData = pData + size;
	}
	if (total_size != m_pInfo->contentSize)
	{
		assert(0);
	}
	return true;
}

void FGSFile::SaveTxt(const char* pcFileName)
{
	CreatDir((char*)GetFileDir(pcFileName).c_str());
	FILE* fp = fopen(pcFileName, "wb");
	static std::string content = "";
	content.clear();
	content.append(std::format("contentSize: {0}\nflag: {1}\ncount: {2}\n", m_pInfo->contentSize, m_pInfo->m_flag, m_pInfo->count));
	
	for (int i = 0; i < m_pInfo->count; i++)
	{
		Info2* pInfo = m_unKnow1[i];

		content.append(std::format("{0:04X}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\n",
						pInfo->m_unKnow1.value,
						pInfo->m_unKnow2,
						pInfo->m_unKnow3,
						pInfo->m_unKnow4,
						pInfo->m_unKnow5,
						pInfo->m_unKnow6,
						pInfo->m_unKnow7,
						pInfo->m_unKnow8,
						pInfo->m_unKnow9,
						pInfo->m_unKnow10,
						pInfo->m_unKnow11,
						pInfo->size)
		);
	}


	auto fileName = GetFileName(pcFileName);
	for (int i = 0; i < m_pInfo->count; i++)
	{
		Info2 *pInfo = m_unKnow1[i];
		if (pInfo->m_unKnow1.value)
		{
			content.append(std::format("{0:04X}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\n",
				pInfo->m_unKnow1.value,
				pInfo->m_unKnow2,
				pInfo->m_unKnow3,
				pInfo->m_unKnow4,
				pInfo->m_unKnow5,
				pInfo->m_unKnow6,
				pInfo->m_unKnow7,
				pInfo->m_unKnow8,
				pInfo->m_unKnow9,
				pInfo->m_unKnow10,
				pInfo->m_unKnow11,
				pInfo->size));
			cv::Mat img = cv::Mat(pInfo->m_unKnow11, pInfo->m_unKnow10, CV_8UC4);
			img = 0;
			for (size_t j = 0; j < pInfo->size; ++j) {
				content.append(std::format("{:02X} ", ((unsigned char*)pInfo->pData)[j]));
			}
			content.append("\n");

			int last_x = 0;
			int row = 0;
			bool newLine = false;
			for (size_t j = 0; j < pInfo->size; ++j) {
				int v = ((unsigned char*)pInfo->pData)[j];
				int count = ((unsigned char*)pInfo->pData)[j + 1];
				content.append(std::format("{:02X} {:02X} ", v, count));
				if (last_x + v + count > pInfo->m_unKnow10)
				{
					newLine = true;
				}
				if (newLine)
				{
					last_x = 0;
					content.append("\n");
					newLine = false;
					row++;
				}
				if (count > 0)
				{
					content.append(std::string(v, ' '));
					content.append(std::string(count, '*'));
					last_x += v;
					for (int k = 0; k < count; k++)
					{
						cv::Vec3b color = palette[((unsigned char*)pInfo->pData)[k + j + 2]];
						img.at<cv::Vec4b>(row, last_x + k) = cv::Vec4b(color[2], color[1], color[0], 255);
					}
					last_x += count;
				}
				else
				{
					newLine = true;
				}
				j+=(count+1);
			}
			content.append("\n\n");

			cv::imwrite(std::format("D:/Image2/{0}_{1}_{2}.png", fileName, pInfo->m_unKnow1.sValue.m_unKnow1_3, pInfo->m_unKnow1.sValue.m_unKnow1_4), img);
		}
	}

	fwrite(content.c_str(), content.size(), 1, fp);

	fclose(fp);
}
void FGSFile::Export(std::string dir)
{
	CreatDir((char*)dir.c_str());

	static std::string content = "";

	for (int i = 0; i < m_pInfo->count; i++)
	{
		Info2* pInfo = m_unKnow1[i];
		if (pInfo->m_unKnow1.value)
		{
			cv::Mat img = cv::Mat(pInfo->m_unKnow11, pInfo->m_unKnow10, CV_8UC4);
			img = 0;
			int last_x = 0;
			int row = 0;
			bool newLine = false;
			for (size_t j = 0; j < pInfo->size; ++j) {
				int v = ((unsigned char*)pInfo->pData)[j];
				int count = ((unsigned char*)pInfo->pData)[j + 1];
				if (last_x + v + count > pInfo->m_unKnow10)
				{
					newLine = true;
				}
				if (newLine)
				{
					last_x = 0;
					newLine = false;
					row++;
				}
				if (count > 0)
				{
					last_x += v;
					for (int k = 0; k < count; k++)
					{
						cv::Vec3b color = palette[((unsigned char*)pInfo->pData)[k + j + 2]];
						img.at<cv::Vec4b>(row, last_x + k) = cv::Vec4b(color[2], color[1], color[0], 255);
					}
					last_x += count;
				}
				else
				{
					newLine = true;
				}
				j += (count + 1);
			}
			std::string saveImage = std::format("{0}/{1}_{2}_{3}.png", dir.c_str(), m_name.c_str(), pInfo->m_unKnow1.sValue.m_unKnow1_3, pInfo->m_unKnow1.sValue.m_unKnow1_4);
			cv::imwrite(saveImage, img);
		}
	}
}